﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Newtonsoft.Json;
using YEA.Infrastructure.Gateway;

namespace YEA.Utilities.Notifications.Converter
{
    public class NotificationConverter : IConvertToMessage
    {
        public const string PLAIN_TEXT = "text/plain";
        public const string DEFAULT_CHAR_SET = "utf-8";
        public const string CONTENT_TYPE = "application/json";
        public string CharSet { get; set; }

        public NotificationConverter()
        {
            CharSet = DEFAULT_CHAR_SET;
        }

        public Message ConvertObjectToMessage(RabbitMQ.Client.IModel channel, object packetToSend)
        {
            Notification message = (Notification)packetToSend;
            if (channel == null)
                throw new ArgumentException("The channel is null, a valid channel is required to create a message");
            
            byte[] bytes = null;
            var properties = channel.CreateBasicProperties();
            var json = JsonConvert.SerializeObject(message);
            bytes = Encoding.GetEncoding(CharSet).GetBytes(json);
            properties.ContentType = CONTENT_TYPE;
            properties.ContentEncoding = CharSet;
            properties.Headers = new Dictionary<string, object>();
            properties.Headers.Add("type", message.GetType().ToString());
            return new Message() { Body = bytes, Properties = properties, RoutingKey = string.Empty };
        }

        public Notification ConvertMessageToObject(Message message)
        {
            if (message == null)
                throw new ArgumentException("The message passed to the converter is null");
            var properties = message.Properties;
            if (properties == null)
                throw new ArgumentException("Message properties are required to convert the message to a notification");


            if (properties.ContentEncoding == DEFAULT_CHAR_SET
                && properties.ContentType == CONTENT_TYPE
                && properties.Headers["type"].ToString() == typeof(Notification).ToString())
            {
                return ConvertBytesToNotification(message.Body);
            }
            throw new FormatException("Can't convert message to notification, the message contains an invalid serialized object");
        }
        public Notification ConvertBytesToNotification(byte[] value)
        {
            Notification retval = null;
            using (var stream = new MemoryStream(value))
            {
                var encoding = Encoding.GetEncoding(CharSet);
                var reader = new StreamReader(stream, encoding, false);
                var jsonReader = new JsonTextReader(reader);
                var jsonSerializer = new JsonSerializer();
                retval = jsonSerializer.Deserialize(jsonReader, typeof(Notification)) as Notification;
            }
            return retval;
        }
    }
}
